from typing import List, Tuple

import jieba
from sklearn.feature_extraction.text import TfidfVectorizer
import re
from collections import defaultdict
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from sentence_transformers import SentenceTransformer
import warnings
warnings.filterwarnings("ignore", category=UserWarning)

class MedicalSimilarity:
    def __init__(self):
        self.model = SentenceTransformer('./experiments/bert-base-chinese/')
        # 医学术语标准化词典
        self.term_mapping = {
            # 解剖部位标准化
            r'胸廓对称': '胸廓对称',
            r'气管居中': '气管居中',
            r'右肺下叶': '右肺下叶',
            r'主动脉壁': '主动脉壁',
            r'肝内外胆管': '胆管系统',

            # 病变描述标准化
            r'小斑片状略高密度影': '斑片影',
            r'边界欠清': '边界模糊',
            r'类圆形低密度影': '低密度结节',
            r'囊状扩张': '囊状改变',
            r'双输尿管走行': '输尿管重复畸形',

            # 影像表现标准化
            r'未见明显异常密度影': '未见异常密度影',
            r'未见明显肿大淋巴结': '淋巴结未见肿大',
            r'未见局灶性密度异常': '未见异常密度灶',
            r'大小形态及密度正常': '形态密度正常',
            r'走行正常': '走行自然',

            # 复合术语标准化
            r'右肾静脉呈囊状扩张': '右肾静脉扩张',
            r'静脉壁见致密影': '静脉壁钙化',
            r'各叶段支气管开口通畅': '支气管通畅',
            r'腹膜后未见肿大淋巴结': '腹膜后淋巴结正常',
            r'肝内血管走行正常': '肝血管走行自然',

            # 新增器官部位别名
            r'右下肺叶': '右肺下叶',
            r'左肝外叶': '左外叶肝',
            r'右肾静脉系统': '右肾静脉',
            r'腹膜后区': '腹膜后',
            r'主气道': '气管',

            # CT专用术语
            r'高密度灶': '高密度影',
            r'低CT值区': '低密度区',
            r'增强扫描明显强化': '明显强化',
            r'CT值约\d+HU': 'CT值异常',
            r'窗宽窗位': '窗设置',

            # MRI专用术语
            r'T1WI高信号': 'T1高信号',
            r'T2WI低信号': 'T2低信号',
            r'DWI弥散受限': '弥散受限',
            r'ADC值减低': 'ADC值降低',
            r'增强扫描未见强化': '无强化',

            # 多模态通用术语
            r'占位性病变': '占位',
            r'异常信号灶': '异常信号',
            r'血流信号': '血供',

            # 器官系统别名
            r'胆道系统': '胆管系统',
            r'心血管系统': '心脏大血管',
            r'中枢神经系统': '脑脊髓系统'
        }
        # 关键特征提取正则
        self.feature_pattern = re.compile(
            r'(\d+[×x]\d+mm)|([上下左右前后]+叶)|(增[高强]|减低)|([轻中重]度)'
        )

    def normalize_terms(self, text):
        """术语标准化处理"""
        for pattern, replacement in self.term_mapping.items():
            text = re.sub(pattern, replacement, text)
        return text

    def extract_features(self, text):
        """提取医学关键特征"""
        features = defaultdict(float)

        # 结构特征匹配
        size_match = re.search(r'(\d+)[×x](\d+)mm', text)
        if size_match:
            w, h = map(int, size_match.groups())
            features['size'] = np.log1p(w * h)  # 尺寸对数化

        # 关键词权重
        anatomy_terms = ['叶', '段', '脑室', '脑干', '支气管']
        for term in anatomy_terms:
            if term in text:
                features[f'anatomy_{term}'] = 1.0

        pathology_terms = [
            '高密度', '钙化', '肿大', '增厚',
            '肿胀', '骨折', '支扩', '致密',
            '结节', '扩张', '模糊', '积液',
            '膨出', '受压', '骨赘', '肥厚',
            '突出', '钙化', '增厚', '狭窄'
        ]
        for term in pathology_terms:
            features[f'pathology_{term}'] = 1.5 if term in text else 0  # 病理特征加权

        return features

    def semantic_similarity(self, a, b):
        """深度语义相似度"""
        embeddings = self.model.encode([a, b])
        return cosine_similarity([embeddings[0]], [embeddings[1]])[0][0]

    def __call__(self, text_a, text_b):
        # 预处理
        a_norm = self.normalize_terms(text_a)
        b_norm = self.normalize_terms(text_b)

        # 特征相似度（结构特征+关键词）
        feat_a = self.extract_features(a_norm)
        feat_b = self.extract_features(b_norm)
        all_keys = set(feat_a.keys()) | set(feat_b.keys())
        vec_a = np.array([feat_a.get(k, 0) for k in all_keys])
        vec_b = np.array([feat_b.get(k, 0) for k in all_keys])
        feature_sim = cosine_similarity([vec_a], [vec_b])[0][0]

        # 语义相似度
        semantic_sim = self.semantic_similarity(a_norm, b_norm)

        # 综合加权（特征相似度占70%，语义相似度占30%）
        return 0.4 * feature_sim + 0.6 * semantic_sim


def extract_associations_data(data):
    """
    提取解剖部位与病变的关联关系
    同样存在一对多和多对一的情况
    """
    associations = {}
    current_anatomy = []
    for item in data:
        desc, category = item
        if category == '解剖部位':
            current_anatomy.append(desc)
        elif category == '病变或异常':
            if current_anatomy:
                # 将当前累积的所有解剖部位作为键
                anatomy_key = ' '.join(current_anatomy)
                associations.setdefault(anatomy_key, []).append(desc)
                # 清空累积的解剖部位
                current_anatomy = []
        else:
            # 遇到其他类别时清空累积的解剖部位
            current_anatomy = []
    return associations


def detected_conflict(
    image_observations: List[Tuple[str, str]],
    diagnosis_results: List[Tuple[str, str]]
) -> List[dict]:
    def extract_associations_data(data):
        """
        提取解剖部位与病变的关联关系
        同样存在一对多和多对一的情况
        """
        associations = {}
        current_anatomy = []
        for item in data:
            desc, category = item
            if category == '解剖部位':
                current_anatomy.append(desc)
            elif category == '病变或异常':
                if current_anatomy:
                    # 将当前累积的所有解剖部位作为键
                    anatomy_key = ' '.join(current_anatomy)
                    associations.setdefault(anatomy_key, []).append(desc)
                    # 清空累积的解剖部位
                    current_anatomy = []
            else:
                # 遇到其他类别时清空累积的解剖部位
                current_anatomy = []
        return associations

    image_anatomy = extract_associations_data(image_observations)
    diag_anatomy = extract_associations_data(diagnosis_results)

    def split_anatomy_abnormalities(data_dict: dict) -> List[Tuple[str, str]]:
        """将复合解剖部位与对应的异常描述拆分对齐"""
        result = []
        for anatomy_key, abn_list in data_dict.items():
            if not abn_list:  # 处理空列表情况
                continue
            # 拆分复合解剖部位并用第一个异常描述
            for single_anatomy in anatomy_key.split():
                result.append((single_anatomy, abn_list[0]))
        return result
    data_image_anatomy = split_anatomy_abnormalities(image_anatomy)
    diag_image_anatomy = split_anatomy_abnormalities(diag_anatomy)

    # 修改正则表达式和对比逻辑 ↓
    def extract_directional_parts(name):
        """更精确的方位词提取"""
        direction_pattern = r'^(双侧|左侧|右侧|左|右|前|后|上|下|内|外)(.+)'
        match = re.match(direction_pattern, name)
        return (match.group(1), match.group(2).strip()) if match else (None, name)

    # 构建映射时记录完整主体
    image_directions = {}
    for ent, _ in data_image_anatomy:
        direction, base = extract_directional_parts(ent)
        image_directions[base] = image_directions.get(base, set())
        image_directions[base].add(direction)

    diag_directions = {}
    for ent, _ in diag_image_anatomy:
        direction, base = extract_directional_parts(ent)
        diag_directions[base] = diag_directions.get(base, set())
        diag_directions[base].add(direction)

    # 只对比共同存在的主体部位
    direction_errors = []
    common_bases = set(image_directions.keys()) & set(diag_directions.keys())
    for base in common_bases:
        img_dirs = image_directions[base]
        diag_dirs = diag_directions[base]

        # 只有当主体完全相同时才对比方位词
        if not img_dirs.intersection(diag_dirs):
            error_msg = {
                '类型': '方位词冲突',
                '详情': f"解剖部位 '{base}' 方位描述不一致：影像侧为 {list(img_dirs)}，诊断侧为 {list(diag_dirs)}"
            }
            direction_errors.append(error_msg)

    return direction_errors  # 根据实际需要返回错误信息


def process_medical_report(
    image_observations: List[Tuple[str, str]],
    diagnosis_results: List[Tuple[str, str]]
) -> List[dict]:
    """
    处理医学影像报告，对比影像所见和诊断结果的异常实体
    current_anatomy当前代表实体：解剖位置
    image_abnormalities当前代表实体：图像异常
    """
    def extract_associations(data):
        """
        提取解剖部位与病变的关联关系
        同样存在一对多和多对一的情况
        """
        associations = {}
        current_anatomy = []
        for item in data:
            desc, category = item
            if category == '解剖部位':
                current_anatomy.append(desc)
            elif category == '病变或异常':
                if current_anatomy:
                    # 将当前累积的所有解剖部位作为键
                    anatomy_key = ' '.join(current_anatomy)
                    associations.setdefault(anatomy_key, []).append(desc)
                    # 清空累积的解剖部位
                    current_anatomy = []
            else:
                # 遇到其他类别时清空累积的解剖部位
                current_anatomy = []
        return associations

    def extract_associations_image(data):
        """
        提取解剖部位与病变的关联关系
        相关问题有：
        1. 存在多个异常描述对应同一个解剖部位的情况
        2. 存在多个解剖部位对应一个异常描述的情况
        """
        current_anatomy = []
        abnormality_dict = defaultdict(list)  # 存储异常描述与解剖部位的映射

        # 第一阶段：收集所有异常描述对应的解剖部位
        for item in data:
            desc, category = item
            if category == '解剖部位':
                current_anatomy.append(desc)
            elif category == '病变或异常':
                if current_anatomy:
                    # 使用有序字典去重，保留最后出现的解剖部位顺序
                    seen = dict.fromkeys(current_anatomy)
                    unique_anatomy = list(seen.keys())

                    # 合并历史数据并去重
                    combined = list(dict.fromkeys(abnormality_dict[desc] + unique_anatomy))
                    abnormality_dict[desc] = combined  # 更新合并后的解剖部位
                current_anatomy = []
            else:
                current_anatomy = []

        # 第二阶段：生成最终关联关系（已合并旧数据）
        associations = defaultdict(list)
        for abn, anatomies in abnormality_dict.items():
            anatomy_key = ' '.join(anatomies)
            associations[anatomy_key].append(abn)

        return associations

        # 新增诊断专用处理函数
    image_findings = image_observations
    diagnosis = diagnosis_results
    image_assoc = extract_associations_image(image_findings)
    diag_assoc = extract_associations(diagnosis)


    def knowledge_fusion(image_assoc, diag_assoc):
        """融合图像和诊断的关联信息"""
        medical_sim = MedicalSimilarity()

        # 影像知识融合
        image_embeddings = {}
        for anatomy, image_abns in image_assoc.items():
            # 拼接异常描述并编码
            combined_abn = '，'.join(image_abns)
            image_embeddings[anatomy] = medical_sim.model.encode(combined_abn)

        # 诊断知识融合
        diag_embeddings = {}
        for anatomy, diag_abns in diag_assoc.items():
            # 拼接诊断描述并编码
            combined_abn = '，'.join(diag_abns)
            diag_embeddings[anatomy] = medical_sim.model.encode(combined_abn)

        return image_embeddings, diag_embeddings

    # 在调用处添加融合逻辑
    image_embeddings, diag_embeddings = knowledge_fusion(image_assoc, diag_assoc)

    def entity_fusion(embeddings, assoc_data):
        """单参数实体融合，保持原有数据结构"""
        from sklearn.cluster import AgglomerativeClustering
        from sklearn.preprocessing import normalize

        # 关键优化1：对嵌入向量进行L2归一化
        all_anatomy = list(embeddings.keys())
        anatomy_vectors = normalize([embeddings[a] for a in all_anatomy])  # 新增归一化

        clustering = AgglomerativeClustering(
            n_clusters=None,
            distance_threshold=0.3,  # 优化点2：降低距离阈值提升精度
            metric='euclidean',
            linkage='ward'  # 优化点3：改用ward方法
        ).fit(anatomy_vectors)

        # 构建合并后的关联字典
        merged_assoc = {}
        for cluster_id in np.unique(clustering.labels_):
            cluster_indices = np.where(clustering.labels_ == cluster_id)[0]
            anatomies = [all_anatomy[i] for i in cluster_indices]

            # 新增筛选条件：仅合并确实相似的解剖部位
            if len(anatomies) > 1:
                cluster_vectors = [anatomy_vectors[i] for i in cluster_indices]
                avg_sim = np.mean(cosine_similarity(cluster_vectors))
                if avg_sim < 0.65:  # 添加平均相似度阈值
                    continue

            # 合并异常描述
            combined_abn = list(set(
                [abn for a in anatomies for abn in assoc_data.get(a, [])]
            ))

            # 保留主解剖部位
            main_anatomy = max(anatomies, key=lambda x: len(assoc_data.get(x, [])))
            merged_assoc[main_anatomy] = combined_abn

        return merged_assoc

    # # 修改调用方式
    # if len(image_assoc) > 1:
    #     image_assoc_merged = entity_fusion(image_embeddings, image_assoc)
    #     diag_assoc_merged = entity_fusion(diag_embeddings, diag_assoc)
    # else:
    #     image_assoc_merged = image_assoc
    #     diag_assoc_merged = diag_assoc
    # # 在打印部分添加融合结果
    # print('影像对齐之后的:', image_assoc_merged)
    # print('诊断对齐之后的', diag_assoc_merged)

    # 按顺序获取解剖部位列表
    image_anatomy = list(image_assoc.keys())
    diag_anatomy = list(diag_assoc.keys())
    image_list = image_anatomy.copy()
    diag_list = diag_anatomy.copy()
    results = []

    def simple_similarity(a: str, b: str) -> float:
        """TF-IDF余弦相似度计算"""
        # 处理空字符串情况
        if not a or not b:
            return 0.0

        # 使用结巴分词进行TF-IDF向量化
        corpus = [a, b]
        tfidf = TfidfVectorizer(
            tokenizer=jieba.cut,  # 使用结巴分词
            min_df=1  # 处理单个词语
        )
        try:
            tfidf_matrix = tfidf.fit_transform(corpus)
            return cosine_similarity(tfidf_matrix[0:1], tfidf_matrix[1:2])[0][0]
        except:
            return 0.0

    while image_list and diag_list:
        # 寻找最佳匹配对
        max_sim = -1
        best_pair = (None, None)
        for img_item in image_list:
            for diag_item in diag_list:
                current_sim = simple_similarity(img_item, diag_item)
                if current_sim > max_sim:
                    max_sim = current_sim
                    best_pair = (img_item, diag_item)
        if max_sim > 0.5:
            img_key, diag_key = best_pair
            # 相似度阈值
            # 处理匹配成功的异常
            img_abn = image_assoc[img_key]
            diag_abn = diag_assoc[diag_key]
            text_a = '，'.join(img_abn)  # 原为 img_abn[0]
            text_b = '，'.join(diag_abn)  # 原为 diag_abn[0]
            sim = MedicalSimilarity()
            similarity = sim(text_a, text_b)
            text_a = []
            text_b = []
            if similarity < 0.5:
                for ibn in img_abn:
                    for dbn in diag_abn:
                        results.append({
                            '解剖部位': img_key,
                            '影像异常': ibn,
                            '诊断异常': dbn,
                            '状态': '解释性不足',
                            '详情': f'解剖部位 [{img_key}] 及其异常 [{ibn}] 与诊断 [{dbn}] 解释性不足'
                            f'，相似度为 [{similarity}] '
                        })
                image_list.remove(img_key)
                diag_list.remove(diag_key)
            if similarity >= 0.5:
                image_list.remove(img_key)
                diag_list.remove(diag_key)
        elif max_sim <= 0.5:
            # 处理匹配失败的异常
            img_key, diag_key = best_pair
            # 相似度阈值
            # 处理匹配成功的异常
            img_abn = image_assoc[img_key]
            diag_abn = diag_assoc[diag_key]
            text_a = '，'.join(img_abn)  # 原为 img_abn[0]
            text_b = '，'.join(diag_abn)  # 原为 diag_abn[0]
            sim = MedicalSimilarity()
            similarity = sim(text_a, text_b)
            text_a = []
            text_b = []
            if similarity < 0.5:
                for ibn in img_abn:
                    for dbn in diag_abn:
                        results.append({
                            '解剖部位': img_key,
                            '影像异常': ibn,
                            '诊断异常': dbn,
                            '状态': '解释性不足',
                            '详情': f'解剖部位 [{img_key}] 及其异常 [{ibn}] 与诊断 [{dbn}] 解释性不足'
                            f'，相似度为 [{similarity}] '
                        })
                image_list.remove(img_key)
                diag_list.remove(diag_key)
            if similarity >= 0.5:
                image_list.remove(img_key)
                diag_list.remove(diag_key)

    # 处理剩余未匹配的解剖部位
    for img_key in image_list:
        for abn in image_assoc[img_key]:
            results.append({
                '解剖部位': img_key,
                '影像异常': abn,
                '诊断异常': '无',
                '状态': '诊断遗漏',
                '详情': f'解剖部位 {img_key} 及其异常 {abn} 未在诊断体现'
            })

    for diag_key in diag_list:
        for abn in diag_assoc[diag_key]:
            results.append({
                '解剖部位': diag_key,
                '影像异常': '无',
                '诊断异常': abn,
                '状态': '影像未发现',
                '详情': f'解剖部位 {diag_key} 及其异常 {abn} 未在影像发现'
            })
    return results
    # max_length = max(len(image_anatomy), len(diag_anatomy))
    # results = []
    # for i in range(max_length):
    #     img_key = image_anatomy[i] if i < len(image_anatomy) else None
    #     diag_key = diag_anatomy[i] if i < len(diag_anatomy) else None
    #
    #     # 获取异常列表
    #     img_abn = image_assoc[img_key] if img_key else []
    #     diag_abn = diag_assoc[diag_key] if diag_key else []
    #     # 处理影像多余解剖部位
    #     if img_key and not diag_key:
    #         for abn in img_abn:
    #             results.append({
    #                 '解剖部位': img_key,
    #                 '影像异常': abn,
    #                 '诊断异常': '无',
    #                 '状态': '诊断遗漏',
    #                 '详情': f'解剖部位 {img_key} 及其异常 {abn} 未在诊断体现'
    #             })
    #     # 处理诊断多余解剖部位
    #     elif diag_key and not img_key:
    #         for abn in diag_abn:
    #             results.append({
    #                 '解剖部位': diag_key,
    #                 '影像异常': '无',
    #                 '诊断异常': abn,
    #                 '状态': '影像未发现',
    #                 '详情': f'解剖部位 {diag_key} 及其异常 {abn} 未在影像发现'
    #             })
    #     else:
    #         text_a = img_abn[0]
    #         text_b = diag_abn[0]
    #         sim = MedicalSimilarity()
    #         similarity = sim(text_a, text_b)
    #         if similarity < 0.5:
    #             for ibn in img_abn:
    #                 for dbn in diag_abn:
    #                     results.append({
    #                         '解剖部位': img_key,
    #                         '影像异常': ibn,
    #                         '诊断异常': dbn,
    #                         '状态': '解释性不足',
    #                         '详情': f'解剖部位 [{img_key}] 及其异常 [{ibn}] 与诊断 [{dbn}] 解释性不足'
    #                         f'，相似度为 [{similarity}] '
    #                     })
    #         if similarity >= 0.5:
    #             continue
    #     if results == []:
    #         results.append({
    #             '状态': '无异常'
    #         })
    # return results


if __name__ == '__main__':
    # 使用示例
    # image_findings = [('双侧大脑半球', '解剖部位'), ('对称', '影像学表现'), ('灰白质', '解剖部位'), ('对比正常', '影像学表现'),
    #                  ('左侧额叶', '解剖部位'), ('颅板下', '解剖部位'), ('见径约8×15mm的致密影', '病变或异常'),
    #                  ('边界清', '影像学表现'), ('颅骨宽基底', '解剖部位'), ('邻近颅骨骨皮质', '解剖部位'),
    #                  ('毛糙', '影像学表现'), ('各脑室', '解剖部位'), ('脑池', '解剖部位'),
    #                  ('大小形态正常', '影像学表现'), ('中线结构', '解剖部位'), ('居中', '影像学表现'),
    #                  ('幕下小脑', '解剖部位'), ('脑干', '解剖部位'), ('无异常', '影像学表现'),
    #                  ('胸廓', '解剖部位'), ('对称', '影像学表现'), ('气管', '解剖部位'), ('居中', '影像学表现'),
    #                  ('两肺下叶', '解剖部位'), ('见条带状高密度影', '病变或异常'), ('余肺内', '解剖部位'),
    #                  ('未见明显异常密度影', '影像学表现'), ('各叶段支气管', '解剖部位'), ('开口通畅', '影像学表现'),
    #                  ('纵隔内', '解剖部位'), ('未见明显肿大淋巴结', '影像学表现'), ('心脏大血管', '解剖部位'),
    #                  ('未见明显异常密度影', '影像学表现')]
    #
    # diagnosis = [('左侧额叶', '解剖部位'), ('结节状高密度影', '病变或异常'),
    #             ('两肺下叶', '解剖部位'), ('轻度间质性炎症', '病变或异常'),
    #             ('右肝前叶上段', '解剖部位'), ('囊性灶', '病变或异常'), ('囊肿', '病变或异常')]

    image_findings = [('左侧上颌窦', '解剖部位'), ('左侧筛窦', '解剖部位'), ('见粘膜增厚影', '病变或异常'),
                        ('蝶窦', '解剖部位'), ('额窦内', '解剖部位'), ('未见明显粘膜增厚影', '影像学表现'),
                        ('鼻中隔', '解剖部位'), ('增厚', '病变或异常'), ('左侧鼻腔内', '解剖部位'),
                        ('见粘膜增厚影', '病变或异常'), ('鼻咽腔', '解剖部位'), ('大小、形态尚好', '影像学表现'),
                        ('两侧咽鼓管', '解剖部位'), ('咽隐窝', '解剖部位'), ('均称', '影像学表现'),
                        ('两侧咽旁', '解剖部位'), ('间隙存在', '影像学表现'), ('胸廓', '解剖部位'),
                        ('对称', '影像学表现'), ('气管', '解剖部位'), ('居中', '影像学表现'), ('右肺上叶', '解剖部位'),
                        ('见疑似小结节状高密度影', '病变或异常'), ('余肺内', '解剖部位'),
                        ('未见明显异常密度影', '影像学表现'), ('各叶段支气管', '解剖部位'), ('开口通畅', '影像学表现'),
                        ('纵隔内', '解剖部位'), ('未见明显肿大淋巴结', '影像学表现'), ('心脏大血管', '解剖部位'),
                        ('未见明显异常密度影', '影像学表现')]
    diagnosis = [('右侧上颌窦', '解剖部位'), ('左侧筛窦', '解剖部位'), ('右侧鼻腔内', '解剖部位'),
                        ('炎症', '病变或异常'), ('右肺上叶', '解剖部位'), ('小结节', '病变或异常'),
                        ('增殖灶', '病变或异常')]
    # image_findings = [('两肺', '解剖部位'), ('透光度良好', '影像学表现'), ('两肺', '解剖部位'), ('纹理分布清晰', '影像学表现'),
    #  ('右肺下叶后段', '解剖部位'), ('见一小结节状', '病变或异常'), ('囊状支扩影', '病变或异常'), ('余两肺', '解剖部位'),
    #  ('未见明显异常密度影', '影像学表现'), ('气管', '解剖部位'), ('主支气管', '解剖部位'), ('各叶段支气管', '解剖部位'),
    #  ('通畅', '影像学表现'), ('纵隔内', '解剖部位'), ('未见明显肿大淋巴结', '影像学表现'), ('心影', '解剖部位'),
    #  ('大小形态正常', '影像学表现'), ('心包', '解剖部位'), ('两侧胸腔', '解剖部位'), ('无积液', '影像学表现')]
    # diagnosis = [('左肺下叶后段', '解剖部位'), ('小支扩影', '病变或异常')]

    result_organ = detected_conflict(image_findings, diagnosis)
    print("-" * 110)
    for idx, item in enumerate(result_organ, 1):
        print(item)

    result_image = process_medical_report(image_findings, diagnosis)
    header = f"{'序号':<4} | {'解剖部位':<14} | {'影像异常':<18} | {'诊断异常':<18} | {'状态':<8} | 详情"
    print(header)
    print("-" * 110)
    for idx, item in enumerate(result_image, 1):
        print(
            f"{idx:<4} | {item['解剖部位']:<14} | "
            f"{item['影像异常']:<18} | "
            f"{item['诊断异常']:<18} | "
            f"{item['状态']:<8} | "
            f"{item['详情']}"
    )